{
 "metadata": {
  "name": "",
  "signature": "sha256:dca9f807a72d347aff1673d48e6784e765fa605f77edb8b87cc9654049766572"
 },
 "nbformat": 3,
 "nbformat_minor": 0,
 "worksheets": [
  {
   "cells": [
    {
     "cell_type": "heading",
     "level": 1,
     "metadata": {},
     "source": [
      "Fetal Electrocardiogram Extraction by Source Subspace Separation"
     ]
    },
    {
     "cell_type": "heading",
     "level": 4,
     "metadata": {},
     "source": [
      "By Kevin Hughes and Andreas Ziehe"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "This notebook illustrates <a href=\"http://en.wikipedia.org/wiki/Blind_signal_separation\">Blind Source Seperation</a>(BSS) on several time synchronised Electrocardiogram's (ECG's) of the baby's mother using <a href=\"http://en.wikipedia.org/wiki/Independent_component_analysis\">Independent Component Analysis</a> (ICA) in Shogun. This is used to extract the baby's ECG from it."
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "This task has been studied before and has been published in these papers:\n",
      "\n",
      "Cardoso, J. F. (1998, May). Multidimensional independent component analysis. \n",
      "In Acoustics, Speech and Signal Processing, 1998. Proceedings of the 1998 \n",
      "IEEE International Conference on (Vol. 4, pp. 1941-1944). IEEE.\n",
      "\n",
      "Dirk Callaerts, \"Signal Separation Methods based on Singular Value\n",
      "Decomposition and their Application to the Real-Time Extraction of the\n",
      "Fetal Electrocardiogram from Cutaneous Recordings\", Ph.D. Thesis,\n",
      "K.U.Leuven - E.E. Dept., Dec. 1989.\n",
      "\n",
      "L. De Lathauwer, B. De Moor, J. Vandewalle, \"Fetal Electrocardiogram\n",
      "Extraction by Source Subspace Separation\", Proc. IEEE SP / ATHOS\n",
      "Workshop on HOS, June 12-14, 1995, Girona, Spain, pp. 134-138.\n",
      "\n",
      "In this workbook I am going to show you how a similar result can be obtained using the ICA algorithms available in the Shogun Machine Learning Toolbox."
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "First we need some data, luckily an ECG dataset is distributed in the Shogun data repository. So the first step is to change the directory then we'll load the data."
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "# change to the shogun-data directory\n",
      "import os\n",
      "os.chdir('../../../data/ica')"
     ],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "import numpy as np\n",
      "\n",
      "# load data\n",
      "# Data originally from:\n",
      "# http://perso.telecom-paristech.fr/~cardoso/icacentral/base_single.html\n",
      "data = np.loadtxt('foetal_ecg.dat')\n",
      "\n",
      "# time steps\n",
      "time_steps = data[:,0]\n",
      "\n",
      "# abdominal signals\n",
      "abdominal2 = data[:,1]\n",
      "abdominal3 = data[:,2]\n",
      "abdominal4 = data[:,3]\n",
      "abdominal5 = data[:,4]\n",
      "abdominal6 = data[:,5]\n",
      "\n",
      "# thoracic signals\n",
      "thoracic7 = data[:,6]\n",
      "thoracic8 = data[:,7]\n",
      "thoracic9 = data[:,8]"
     ],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "Before we go any further let's take a look at this data by plotting it:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%matplotlib inline\n",
      "# plot signals\n",
      "import pylab as pl\n",
      "\n",
      "# abdominal signals\n",
      "for i in range(1,6):\n",
      "    pl.figure(figsize=(14,3))\n",
      "    pl.plot(time_steps, data[:,i], 'r')\n",
      "    pl.title('Abdominal %d' % (i))\n",
      "    pl.grid()\n",
      "    pl.show()\n",
      "\n",
      "# thoracic signals\n",
      "for i in range(6,9):\n",
      "    pl.figure(figsize=(14,3))\n",
      "    pl.plot(time_steps, data[:,i], 'r')\n",
      "    pl.title('Thoracic %d' % (i))\n",
      "    pl.grid()\n",
      "    pl.show()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "The peaks in the plot represent a heart beat but its pretty hard to interpret and I know I definitely can't see two distinc signals, lets see what we can do with ICA!\n",
      "\n",
      "In general for performing Source Separation we need at least as many mixed signals as sources we're hoping to separate and in this case we actually have a lot more (9 mixtures but there is only 2 sources, mother and baby). There are several different approaches for handling this situation, some algorithms are specifically designed to handle this case while other times the data is pre-processed with Principal Component Analysis (PCA). It is also common to simply apply the separation to all the sources and then choose some of the extracted signal manually or using some other know criteria which is what I'll be showing in this example."
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "Now we create our ICA data set and convert to a Shogun features type:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from shogun.Features  import RealFeatures\n",
      "\n",
      "# Signal Matrix X\n",
      "X = (np.c_[abdominal2, abdominal3, abdominal4, abdominal5, abdominal6, thoracic7,thoracic8,thoracic9]).T\n",
      "\n",
      "# Convert to features for shogun\n",
      "mixed_signals = RealFeatures((X).astype(np.float64))"
     ],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "Next we apply the ICA algorithm to separate the sources:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from shogun.Converter import SOBI\n",
      "\n",
      "# Separating with SOBI\n",
      "sep = SOBI()\n",
      "sep.set_tau(1.0*np.arange(0,120))\n",
      "             \n",
      "signals = sep.apply(mixed_signals)\n",
      "\n",
      "S_ = signals.get_feature_matrix()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "And we plot the separated signals:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "# Show separation results\n",
      "\n",
      "# Separated Signal i\n",
      "for i in range(S_.shape[0]):\n",
      "    pl.figure(figsize=(14,3))\n",
      "    pl.plot(time_steps, S_[i], 'r')\n",
      "    pl.title('Separated Signal %d' % (i+1))\n",
      "    pl.grid()\n",
      "    pl.show()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "Now we can interpret the results! First we are going to exploit the known fact that the baby's heart rate is about twice that of the mothers.\n",
      "\n",
      "Our interpretation of the results is as follows:\n",
      "\n",
      "* separated signal 1 ->    baby ECG\n",
      "* separated signal 2 ->    still a bit mixed baby +mother\n",
      "* separated signal 3 ->    baby ECG\n",
      "* separated signal 4 ->    slow drift due to breathing of the mother\n",
      "* separated signal 5 ->    mainly mother ECG but still a bit mixed and noisy\n",
      "* separated signal 6-8 ->  mothers ECG, with 8 being the best\n",
      "\n",
      "And thats the proof of concept Fetal Electrocardiogram Extraction by Source Subspace Separation using the Shogun Machine Learning Toolkit!"
     ]
    }
   ],
   "metadata": {}
  }
 ]
}
